import { CsDouble } from '../common/csDouble.js';
import { CsFundDouble } from '../common/csFundDouble.js';
import { Definition } from '../common/definition.js';
import { DocBase } from '../common/docBase.js';
import { CommonOrderStatus, DocType, CombineOrderType } from '../common/docDefinition.js';
import { Engine } from '../engine.js';
import { FundAccount } from '../funds/fundAccount.js';
import { PendingReceiveOrder } from '../funds/pendingReceiveOrder.js';
import { PendingInventory } from '../inventory/pendingInventory.js';
import { WareHouse } from '../inventory/warehouse.js';
import { TargetObject, TargetObjectPlatformType, TargetObjectType } from '../targetOrg/targetObject.js';
import { Util } from '../../utils/util.js';
import { OrderUtil } from '../../utils/orderUtil.js';
import { CommodityBatchWithTax } from '../sales/sales.js';
import { FunctionPermissionDefinition } from '../platform/functionPermissionDefinition.js';
import { OrderSelfDefFundData } from '../funds/orderSelfDefFundData.js';
import { OrderOtherFundData } from '../funds/orderOtherFundData.js';
import { DealFilter } from '../sales/dealFilter.js';
import { OtherFundDouble } from '../funds/otherFundDouble.js'
import { OtherFeeType } from "../funds/otherFeeType"
import { MetalFeeTypeDefinition } from '../common/metalDefinition.js'
import { CombineMetalBalance } from './combineMetalBalance.js';
/**
 * 委外加工过滤条件
 */
export class MetalCombineOrderFilter extends DealFilter {
    /**
     * 构造函数
     * @param {string|null} storeId 
     */
    constructor(storeId = null) {
        super(storeId);
    }

    /**
     * 克隆过滤器
     * @param {MetalCombineOrderFilter} filter 
     * @returns {MetalCombineOrderFilter}
     */
    static clone(filter) {
        let baseFilter = super.clone(filter);
        let instance = new MetalCombineOrderFilter();
        Object.assign(instance, baseFilter);
        return instance;
    }

    /**
     * 转换为JSON对象
     * @param {boolean} withState 
     * @returns {Object}
     */
    toJson(withState = false) {
        const ret = super.toJson(withState);
        return ret;
    }
}

/**
 * 贵金属综合单据
 */
export class MetalCombineOrder extends DocBase {
    /** @type {SalesContract|null} 编辑前的订单 */


    /** @type {TargetObject} 供应商/客户 */
    _targetObject;

    /** @type {WareHouse} 仓库 */
    wareHouse;

    /** @type {Array<CommodityBatchWithTax>} 销售商品列表 */
    _salesCommodities = [];

    /** @type {Array<CommodityBatchWithTax>} 回购商品列表 */
    _purchaseCommodities = [];


    /** @type {Array<CombineMetalBalance>} 贵金属收支列表 */
    _metalBalances = [];


    /** @type {CsFundDouble|null} 应收总金额 */
    _receiveableAmount = null;

    /** @type {CsFundDouble}  应付总金额 */
    _payableAmount;


    /** @type {CsFundDouble}  收款金额 */
    _receivedAmount;
    /** @type {CsFundDouble|null} 付款金额 */
    _paymentAmount = null;

    /** @type {FundAccount} 收款账户 */
    _fundAccountForReceive;

    /** @type {FundAccount} 收款账户 */
    _fundAccountForPayment;

    /** @type {OrderOtherFundData} 其他费用, 支付费用增加 */
    _otherFunds;

    /** @type {boolean} 快速出库模式 */
    _quickInventoryMode;

    _balanceBefore = CsFundDouble.zero();  // 本次记录后前总账余额
    _balanceAfter = CsFundDouble.zero();  // 本次记录后总账余额


    _isEdited = false; // 是否已修改


    _indexInTransaction = -1;  // 在transaction 中的顺序，用于新建记录，后台按 index 同步 id


    _innerBalance = CsFundDouble.zero();  // 内部总账余额(前端编辑不更新该值，fromJson时 后台赋值，用于汇总显示)

    _combineOrderType = CombineOrderType.NormalRnd; // 单据类型

    _periodId = null; // 结算ID

    get innerBalance() {
        return this._innerBalance;
    }

    // 期初单据才调用该方法
    set innerBalance(value) {
        this._innerBalance = value;
        this._balanceAfter = value;
    }

    get indexInTransaction() {
        return this._indexInTransaction;
    }

    set indexInTransaction(value) {
        this._indexInTransaction = value;
    }

    get fundAccountForReceive() {
        return this._fundAccountForReceive;
    }

    set fundAccountForReceive(value) {
        this._fundAccountForReceive = value;
    }

    get fundAccountForPayment() {
        return this._fundAccountForPayment;
    }

    set fundAccountForPayment(value) {
        this._fundAccountForPayment = value;
    }

    get isEdited() {
        return this._isEdited;
    }

    set isEdited(value) {
        this._isEdited = value;
    }

    get isPeriodInitial() {
        return this._combineOrderType.code === CombineOrderType.PeriodInitalRnd.code;
    }

    get combineOrderType() {
        return this._combineOrderType;
    }

    get periodId() {
        return this._periodId;
    }


    // 获取收和应收盈余 = 收 - 应收  (客户视角)
    // = 0 表示收和应收没有盈余
    // < 0 表示对方欠款
    // > 0 示对方有盈余
    get receiveBalance() {
        if (this._receivedAmount != null || this._receiveableAmount != null) {
            let receivedAmount = this._receivedAmount ?? CsFundDouble.zero();
            let receiveableAmount = this._receiveableAmount ?? CsFundDouble.zero();
            return receivedAmount.sub(receiveableAmount);

        }
        else {
            return null;
        }
    }

    // 获取付和应付盈余 = 付 - 应付 (客户视角)
    // = 0 示付和应付没有盈余
    // < 0 示对方欠款
    // > 0 示对方有盈余

    get payBalance() {

        if (this._payableAmount != null || this._paymentAmount != null) {
            let payableAmount = this._payableAmount ?? CsFundDouble.zero();
            let paymentAmount = this._paymentAmount ?? CsFundDouble.zero();
            return payableAmount.sub(paymentAmount);
        }
        else {
            return null;
        }
    }

    // value CsFundDouble
    // 更新总账 = 前总账 + 收盈余 + 付盈余 (均为客户视角，正数客户盈余)
    setBalanceBefore(value) {
        if (this._combineOrderType.code === CombineOrderType.PeriodInitalRnd.code
            || this._combineOrderType.code === CombineOrderType.SettledRnd.code
        ) {
            // 期末，期初 = innerBalance
            this._balanceAfter = this._innerBalance;
            return;
        }


        this._balanceBefore = value;


        let payBalance = this.payBalance ?? CsFundDouble.zero();
        let receiveBalance = this.receiveBalance ?? CsFundDouble.zero();
        let swapFee = this.swapFee?.fundDouble ?? CsFundDouble.zero();

        this._balanceAfter = this._balanceBefore.add(receiveBalance).add(payBalance).sub(swapFee);
    }

    get balanceAfter() {
        return this._balanceAfter;
    }

    // set balanceAfter(value) {
    //     this._balanceAfter = value;
    // }



    get metalBalances() {
        return this._metalBalances;
    }

    /**
  * Get a SelfDefFundDouble by metalFundType ID
  * @param {string} typeId - The ID of the metalFundType to find
  * @returns {SelfDefFundDouble|null} - The found object or null
  */
    getMetalBalanceByMetalFoundTypeId(typeId) {
        return this._metalBalances.find(item =>
            item.metalFundType && item.metalFundType.id === typeId
        ) || null;
    }

    get otherFunds() {
        return this._otherFunds;
    }

    /// 销售商品金额 CsFundDouble (应收金额)
    get salesCommodityPrice() {
        let price = null;
        this._salesCommodities.forEach(item => {
            if (item.isSettlePrice && item.batchPriceWithTax != null) {
                if (price == null) {
                    price = CsFundDouble.zero();
                }
                price = price.add(item.batchPriceWithTax);
            }
        });
        return price;
    }

    /// 回购商品金额 CsFundDouble  (应付金额)
    get purchaseCommodityPrice() {
        let price = null;
        this._purchaseCommodities.forEach(item => {
            if (item.isSettlePrice && item.batchPriceWithTax != null) {
                if (price == null) {
                    price = CsFundDouble.zero();
                }
                price = price.add(item.batchPriceWithTax);
            }
        });
        return price;
    }

    /// 应收总金额 CsFundDouble
    get receiveableAmount() {
        if (this._receiveableAmount != null) {
            return this._receiveableAmount;
        }
        // 默认应收金额为销售商品金额
        return this.salesCommodityPrice;
    }

    //set receiveableAmount(value) {
    //    this._receiveableAmount = value;
    // }

    /// 应付总金额 CsFundDouble
    get payableAmount() {
        if (this._payableAmount != null) {
            return this._payableAmount;
        }
        // 默认应付金额为回购商品金额 + 其他费用
        return this.purchaseCommodityPrice;
    }

    //set payableAmount(value) {
    //    this._payableAmount = value;
    // }

    /// 收款金额 CsFundDouble
    get receivedAmount() {

        return this._receivedAmount;

    }

    set receivedAmount(value) {
        this._receivedAmount = value;
        this.calculatePriceAndQuantity();
    }

    /// 付款金额 CsFundDouble
    get paymentAmount() {

        return this._paymentAmount;

    }

    set paymentAmount(value) {
        this._paymentAmount = value;
        this.calculatePriceAndQuantity();
    }

    /// 直接出库模式 bool
    get quickInventoryMode() {
        return this._quickInventoryMode;
    }

    set quickInventoryMode(value) {
        this._quickInventoryMode = value;
    }

    /// 销售商品列表
    get salesCommodities() {
        // console.log("salesCommodities", this._salesCommodities);

        return this._salesCommodities;
    }

    /// 回购商品列表
    get purchaseCommodities() {
        return this._purchaseCommodities;
    }

    /**
     * 获取/设置目标客户
     */
    get targetObject() {
        return this._targetObject;
    }

    set targetObject(value) {
        if (this._targetObject?.id !== value.id) {
            this._targetObject = value;
        }
        this.calculatePriceAndQuantity();
    }

    // 按商品ID 获取销售商品详情
    getSalesBatchByCommodityId(commodityId) {
        return this._salesCommodities.find(item => item.commodity.id === commodityId);
    }

    // 按商品ID 获取回购商品详情
    getPurchaseBatchByCommodityId(commodityId) {
        return this._purchaseCommodities.find(item => item.commodity.id === commodityId);
    }

    /**
     * 更新销售商品列表
     * @param {Array<CommodityBatchWithTax>} list 
     */
    updateSalesCommodityList(list) {
        this._salesCommodities = [...list];
        this.calculatePriceAndQuantity();
    }

    /**
     * 更新回购商品列表
     * @param {Array<CommodityBatchWithTax>} list 
     */
    updatePurchaseCommodityList(list) {
        this._purchaseCommodities = [...list];
        this.calculatePriceAndQuantity();
    }

    /**
     * 添加销售商品批次
     * @param {CommodityBatchWithTax} batch 
     */
    addSalesCommodityBatch(batch) {
        this._salesCommodities.push(batch);
        this.calculatePriceAndQuantity();
    }

    /**
     * 添加回购商品批次
     * @param {CommodityBatchWithTax} batch 
     */
    addPurchaseCommodityBatch(batch) {
        this._purchaseCommodities.push(batch);
        this.calculatePriceAndQuantity();
    }

    /**
     * 删除销售商品批次
     * @param {CommodityBatchWithTax} batch 
     * @returns {boolean}
     */
    removeSalesCommodityBatch(batch) {
        const index = this._salesCommodities.indexOf(batch);
        const ret = index > -1;
        if (ret) {
            this._salesCommodities.splice(index, 1);
        }
        this.calculatePriceAndQuantity();
        return ret;
    }

    /**
     * 删除回购商品批次
     * @param {CommodityBatchWithTax} batch 
     * @returns {boolean}
     */
    removePurchaseCommodityBatch(batch) {
        const index = this._purchaseCommodities.indexOf(batch);
        const ret = index > -1;
        if (ret) {
            this._purchaseCommodities.splice(index, 1);
        }
        this.calculatePriceAndQuantity();
        return ret;
    }

    // 更新单据数据，标题
    // metalCommodities 商户支持的所有贵金属商品
    updateOrderInfo(metalCommodities) {
        this.calculatePriceAndQuantity(true);
        this.updateTitle(metalCommodities);
        this.updateCheckStatus();
    }

    // 检查是否更新
    updateCheckStatus() {

        this._isEdited = false;

        // 如果是已有记录，标记为更改过
        if (!Util.isEmpty(this.id)) {
            this._isEdited = true;
        }

        // 空记录，检查各项是否有数据

        if (this._salesCommodities.length > 0) {
            for (let i = 0; i < this._salesCommodities.length; i++) {
                if (this._salesCommodities[i].count != null
                    || this._salesCommodities[i].singlePriceAfterTax != null
                    || this._salesCommodities[i].batchPriceWithTax != null
                ) {
                    this._isEdited = true;
                    return;
                }
            }
        }

        if (this._purchaseCommodities.length > 0)
            for (let i = 0; i < this._purchaseCommodities.length; i++) {
                if (this._purchaseCommodities[i].count != null
                    || this._purchaseCommodities[i].singlePriceAfterTax != null
                    || this._purchaseCommodities[i].batchPriceWithTax != null
                ) {
                    this._isEdited = true;
                    return;
                }
            }


        if (this._paymentAmount != null || this._receivedAmount != null) {
            this._isEdited = true;
            return;
        }

        this._metalBalances.forEach(balance => {
            if (balance.inCount != null || balance.outCount != null || balance.inExpectCount != null ||
                balance.outExpectCount != null
            ) {
                this._isEdited = true;
                return;
            }
        });

        if (this.swapFee.fundDouble != null) {
            this._isEdited = true;
            return;
        }
    }

    /**
     * 计算价格和数量
     * metalCommodities 商户支持的所有贵金属商品
     */
    calculatePriceAndQuantity(calMetalFunds = false) {

        this._receiveableAmount = this.salesCommodityPrice;
        this._payableAmount = this.purchaseCommodityPrice;

        if (this._balanceBefore != null || this.receiveBalance != null
            || this.payBalance != null || this.swapFee.fundDouble != null) {
            let before = this._balanceBefore ?? CsFundDouble.zero();
            let receive = this.receiveBalance ?? CsFundDouble.zero();
            let pay = this.payBalance ?? CsFundDouble.zero();
            let swapFee = this.swapFee.fundDouble ?? CsFundDouble.zero();
            this._balanceAfter = before.add(receive).add(pay).sub(swapFee);
        }

        // 如果提供了贵金属商品，先清楚列表，再重置并计算收支
        if (calMetalFunds) {

            // 计算销售贵金属应付料
            this._salesCommodities.forEach(element => {

                let metalBalance = this.getMetalBalanceByMetalFoundTypeId(element.commodity.metalAccountTypeId);
                metalBalance.outExpectCount = element.countAfterDiscount;
            });

            // 计算销售贵金属应收料
            this._purchaseCommodities.forEach(element => {

                let metalBalance = this.getMetalBalanceByMetalFoundTypeId(element.commodity.metalAccountTypeId);
                metalBalance.inExpectCount = element.countAfterDiscount;
            });
        }

        // console.log("MetalCombineOrder.calculatePriceAndQuantity this._balanceAfter", this._balanceAfter,this);

    }

    // 更新 标题
    updateTitle(metalCommodities) {
        this.title = this._generateTitle(metalCommodities);
    }

    // 更新title
    /**
     * Generate dynamic title based on transaction content
     * Similar to the Excel formula that checks various cells for content
     * @param {Array<SubCommodity>} metalCommodities - List of metal commodities
     * @returns {string} - Generated title
     */
    _generateTitle(metalCommodities) {
        const parts = [];

        // Check for settlement prices in sales commodities
        this._salesCommodities.forEach(salesBatch => {
            if (salesBatch && salesBatch.commodity && salesBatch.count && salesBatch.count.value > 0) {
                // Check if this is a metal commodity and add metal type
                const metalCommodity = metalCommodities.find(c => c.id === salesBatch.commodity.id);
                if (metalCommodity.standard == 'AU') {
                    // Add "结价" for settlement 
                    if (!parts.includes("结价")) {
                        parts.push("结价");
                    }
                } else {
                    if (!parts.includes(metalCommodity.standard)) {
                        parts.push(metalCommodity.standard);
                    }
                }
            }
        });

        // Check for settlement prices in purchase commodities
        this._purchaseCommodities.forEach(purchaseBatch => {
            if (purchaseBatch && purchaseBatch.commodity && purchaseBatch.count && purchaseBatch.count.value > 0) {
                // Check if this is a metal commodity and add metal type
                const metalCommodity = metalCommodities.find(c => c.id === purchaseBatch.commodity.id);
                if (metalCommodity.standard == 'AU') {
                    // Add "结价" for settlement 
                    if (!parts.includes("结价")) {
                        parts.push("结价");
                    }
                } else {
                    if (!parts.includes(metalCommodity.standard)) {
                        parts.push(metalCommodity.standard);
                    }
                }
            }
        });

        // Check for metal fund accounts (incoming gold)
        this._metalBalances.forEach(account => {
            if (account.inCount && account.inCount.value > 0) {


                // Add metal standard if available
                const metalCommodity = metalCommodities.find(c => c.metalAccountTypeId === account.metalFundType.id);
                if (metalCommodity && metalCommodity.standard && !parts.includes(metalCommodity.standard)) {
                    if (metalCommodity.standard == 'AU') {
                        parts.push("来金");
                    }
                    else {
                        parts.push("来" + metalCommodity.standard);
                    }

                }
            }

            if (account.outCount && account.outCount.value > 0) {

                // Add metal standard if available
                const metalCommodity = metalCommodities.find(c => c.metalAccountTypeId === account.metalFundType.id);
                if (metalCommodity && metalCommodity.standard && !parts.includes(metalCommodity.standard)) {
                    if (metalCommodity.standard == 'AU') {
                        parts.push("付金");
                    }
                    else {
                        parts.push("付" + metalCommodity.standard);
                    }
                }
            }
        });

        // Check for received amount
        if (this._receivedAmount && this._receivedAmount.value > 0) {
            parts.push("来款");
        }

        // Check for payment amount
        if (this._paymentAmount && this._paymentAmount.value > 0) {
            parts.push("付款");
        }

        // Join all parts together
        return parts.join("");
    }

    // 检查销售商品是否为空
    _checkSalesCommoditiesIsEmpty() {
        for (let element of this._salesCommodities) {
            if (element.count != null || element.singlePriceAfterTax != null || element.batchPriceWithTax != null) {
                return false;
            }
        }

        return true;


    }

    // 检查采购商品是否为空
    _checkPurchaseCommoditiesIsEmpty() {

        for (let element of this._purchaseCommodities) {
            if (element.count != null || element.singlePriceAfterTax != null || element.batchPriceWithTax != null) {
                return false;
            }
        }

        return true;
    }

    // 判断来金，付金是否均为空
    _checkBalanceIsEmpty() {

        // 更改为 for 循环
        for (let i = 0; i < this._metalBalances.length; i++) {
            let metalBalance = this._metalBalances[i];
            if (metalBalance.inCount != null || metalBalance.outCount != null
                || metalBalance.inExpectCount != null || metalBalance.outExpectCount != null
            ) {
                return false;
            }
        }

        return true;
    }

    // 期初单据判断innerBalance 是否为空
    _isEmptyMetalInnerBalance() {
        for (let i = 0; i < this._metalBalances.length; i++) {
            let metalBalance = this._metalBalances[i];
           if(metalBalance.innerBalance != null){
                return false;
           }
        }
        return true;
    }

    // 判断是否无任何信息
    isEmptyOrder() {

        // console.log("this.isEmptyOrder()", this);

        return this._checkSalesCommoditiesIsEmpty() && this._checkPurchaseCommoditiesIsEmpty()
            && (this._checkBalanceIsEmpty())
            && (!this._receivedAmount)
            && (!this._paymentAmount) && this.operateDate == null && Util.isEmpty(this.remark);
    }

    /**
     * 校验单据合法性
     */
    validateOrder() {

        if(this.periodId){
            return { errorMsg: "该单据已结算，不能修改！" };
        }

        if(this.isPeriodInitial){
            if(this._isEmptyMetalInnerBalance() && this._innerBalance == null){
                return { errorMsg: "期初单据未设置贵存欠料，存欠款" };
            }
            return null;
        }

        // 商品，来金，付金，来款，付款 必须要有一项
        if (this._checkSalesCommoditiesIsEmpty() && this._checkPurchaseCommoditiesIsEmpty()
            && (this._checkBalanceIsEmpty())
            && (!this._receivedAmount)
            && (!this._paymentAmount)

        ) {
            return { errorMsg: "记录无销售回购商品，来金，付金，来款，付款信息！" };
        }

        if (this.operateDate == null) {
            return { errorMsg: "请选择单据日期！" };
        }

        // 销售商品信息完整性校验
        for (let comRrd of this._salesCommodities) {
            // 全空，或是全部设置，则没有问题，部分设置即不完整，报错
            if (
                !((comRrd.count == null && comRrd.singlePriceAfterTax == null && comRrd.batchPriceWithTax == null)
                    || (comRrd.count != null && comRrd.singlePriceAfterTax != null && comRrd.batchPriceWithTax != null))
            ) {
                return { errorMsg: `销售商品 ${comRrd.commodity?.name} 信息不完整！` };
            }
        }

        // 回购商品信息完整性校验
        for (let comRrd of this._purchaseCommodities) {
            // 全空，或是全部设置，则没有问题，部分设置即不完整，报错
            if (
                !((comRrd.count == null && comRrd.singlePriceAfterTax == null && comRrd.batchPriceWithTax == null)
                    || (comRrd.count != null && comRrd.singlePriceAfterTax != null && comRrd.batchPriceWithTax != null))
            ) {
                return { errorMsg: `回购商品 ${comRrd.commodity?.name} 信息不完整！` };
            }
        }

        // 收付款账户
        if (this._receivedAmount && !this._fundAccountForReceive) {
            return { errorMsg: "请选择收款账户！" };
        }

        if (this._paymentAmount && !this._fundAccountForPayment) {
            return { errorMsg: "请选择付款账户！" };
        }



        return null;
    }

    /// 复制    
    resetForCopy({ removeParentAndSourceData = true } = {}) {
        super.resetForCopy({ removeParentAndSourceData: removeParentAndSourceData });

        // 清除商品列表id
        this._salesCommodities.forEach(element => {
            element.id = "";
        });

        this._purchaseCommodities.forEach(element => {
            element.id = "";
        });

        // 重置金额
        this._receiveableAmount = null;
        this._payableAmount = null;
        this._receivedAmount = null;
        this._paymentAmount = null;

        this.calculatePriceAndQuantity();

    }

    // 获取仓息 返回 OtherFundDouble
    get swapFee() {
        return this._otherFunds.getOtherFeeFundAccountByCode(MetalFeeTypeDefinition.SwapFee.code);
    }


    // 添加所有支持的Metal账户，没有添加，已有不重复添加
    addAllSupportMetalAccount() {
        let customerFundAccountTypeList = Engine.profile.org.customerFundAccountTypeList;

        for (let i = 0; i < customerFundAccountTypeList.length; i++) {
            let accountType = customerFundAccountTypeList[i];

            // 检查是否已存在相同ID的metalBalance
            // 找出已存在的 metalBalance
            let existsBalance = this._metalBalances.find(balance => balance.metalFundType.id === accountType.id);

            // 只设置了 id 和 类型           
            if (existsBalance) {
                existsBalance.name = accountType.name;
                existsBalance.code = accountType.code;
            }
            else {
                // 只有不存在时才添加
                this._metalBalances.push(new CombineMetalBalance({ id: '', metalFundType: accountType }));
            }


        }
    }
    /**
     * 主构造函数
     * @param {Object} params 构造参数
     */
    constructor({
        targetObject,
        wareHouse,
        salesCommodities = [],
        purchaseCommodities = [],
        receiveableAmount = null,
        payableAmount = null,
        receivedAmount = null,
        paymentAmount = null,
        fundAccountForReceive = null,
        fundAccountForPayment = null,
        operateDateTime = null,
        innerBalance = null,
        combineOrderType = null,
        periodId = null,

        // super
        id = "",
        storeId = "",
        storeName = "",
        remark = "",
        operator = "",
        operatorId = "",
        docMaker = "",
        status = CommonOrderStatus.WaitReview,
        title = "",
        docCode = "",
        parentDocType = null,
        parentDocCode = "",
        parentDocTitle = "",
        sourceDocType = null,
        sourceDocCode = "",
        sourceDocTitle = "",
        recordDate = null,
        // quickInventoryMode = null,
        metalBalances,
        otherFunds,
    } = {}) {
        super({
            id,
            title,
            docCode,
            storeId,
            storeName,
            status,
            docType: DocType.METAL_COMBINE,
            parentDocType,
            parentDocCode,
            parentDocTitle,
            sourceDocCode,
            sourceDocType,
            sourceDocTitle,
            recordDateTime: recordDate,
            operator,
            operatorId,
            docMaker,
            operateDateTime: operateDateTime,
            remark
        });

        this._targetObject = targetObject;
        this.wareHouse = wareHouse;
        this._salesCommodities = salesCommodities;
        this._purchaseCommodities = purchaseCommodities;
        this._receiveableAmount = receiveableAmount;
        this._payableAmount = payableAmount;
        this._receivedAmount = receivedAmount;
        this._paymentAmount = paymentAmount;
        this._fundAccountForReceive = fundAccountForReceive;
        this._fundAccountForPayment = fundAccountForPayment;
        this._quickInventoryMode = true;  // 默认开启快速模式

        this._metalBalances = metalBalances ?? [];

        this._combineOrderType = combineOrderType ?? CombineOrderType.NormalRnd;

        this._innerBalance = innerBalance ?? CsFundDouble.zero();

        this._periodId = periodId;

        // 添加所有的贵金属账户
        this.addAllSupportMetalAccount();

        this._otherFunds = otherFunds ?? new OrderOtherFundData();

        this._otherFunds.addOtherFeeFundAccount(new OtherFundDouble(
            new OtherFeeType('', MetalFeeTypeDefinition.SwapFee.name, MetalFeeTypeDefinition.SwapFee.code),
            null,
        ))

        this.calculatePriceAndQuantity();


    }

    /**
     * 创建空贵金属综合单据
     * @param {Object} options
     * @returns {MetalCombineOrder}
     */
    static empty({
        id = null,
        operator = null,
        operatorId = null,
        storeId = null,
        storeName = null,
        metalCommodities = [],  // 商户支持的贵金属商品 (贵金属本身)
        isPeriodInitial = false, // 是否为期初记录
    } = {}) {

        // 创建数量为0的商品
        let salesCommodities = [];
        metalCommodities.forEach(element => {
            salesCommodities.push(
                new CommodityBatchWithTax({
                    commodity: element,
                    count: CsDouble.zero(),
                    batchPrice: CsFundDouble.zero(),
                    singlePrice: CsFundDouble.zero(),
                    referPrice: CsFundDouble.zero(),
                    taxRate: 0, // -1 为默认值，从系统参数获取
                }))
        });

        let purchaseCommodities = [];
        metalCommodities.forEach(element => {
            purchaseCommodities.push(
                new CommodityBatchWithTax({
                    commodity: element,
                    count: CsDouble.zero(),
                    batchPrice: CsFundDouble.zero(),
                    singlePrice: CsFundDouble.zero(),
                    referPrice: CsFundDouble.zero(),
                    taxRate: 0, // -1 为默认值，从系统参数获取
                })
            )
        });

        const order = new MetalCombineOrder({
            targetObject: null,
            wareHouse: WareHouse.empty(),
            salesCommodities: salesCommodities,
            purchaseCommodities: purchaseCommodities,
            id: id || "",
            storeId: storeId || "",
            storeName: storeName || "",
            status: CommonOrderStatus.WaitReview,
            operator: operator || "",
            operatorId: operatorId || "",
            isPeriodInitial: isPeriodInitial
        });

        order.wareHouse = OrderUtil.getOrderDefaultWarehouse({
            storeId: order.storeId,
            curWarehouse: order.wareHouse
        });


        order._fundAccountForReceive = OrderUtil.getOrderDefaultFundAccount({
            storeId: order.storeId,
            curFundAccount: order._fundAccountForReceive
        });

        order._fundAccountForPayment = OrderUtil.getOrderDefaultFundAccount({
            storeId: order.storeId,
            curFundAccount: order._fundAccountForPayment
        });


        return order;
    }

    /**
 * 创建空贵金属综合单据
 * @param {Object} options
 * @returns {MetalCombineOrder}
 */
    static emptyWithNull({
        id = null,
        operator = null,
        operatorId = null,
        storeId = null,
        storeName = null,
        metalCommodities = [],  // 商户支持的贵金属商品 (贵金属本身)
        combineOrderType = null, // 单据类型
        targetObject = null,
    } = {}) {

        // 创建数量为0的商品
        let salesCommodities = [];
        metalCommodities.forEach(element => {
            salesCommodities.push(
                new CommodityBatchWithTax({
                    commodity: element,
                    count: null,
                    batchPrice: null,
                    singlePrice: null,
                    referPrice: null,
                    taxRate: 0, // -1 为默认值，从系统参数获取
                }))
        });

        let purchaseCommodities = [];
        metalCommodities.forEach(element => {
            purchaseCommodities.push(
                new CommodityBatchWithTax({
                    commodity: element,
                    count: null,
                    batchPrice: null,
                    singlePrice: null,
                    referPrice: null,
                    taxRate: 0, // -1 为默认值，从系统参数获取
                })
            )
        });

        const order = new MetalCombineOrder({
            targetObject: targetObject,
            wareHouse: WareHouse.empty(),
            salesCommodities: salesCommodities,
            purchaseCommodities: purchaseCommodities,
            id: id || "",
            storeId: storeId || "",
            storeName: storeName || "",
            status: CommonOrderStatus.WaitReview,
            operator: operator || "",
            operatorId: operatorId || "",
            combineOrderType: combineOrderType
        });

        // 清空日期，DocBase 默认会附上当前初始值
        order.operateDate = null;

        order.wareHouse = OrderUtil.getOrderDefaultWarehouse({
            storeId: order.storeId,
            curWarehouse: order.wareHouse
        });


        return order;
    }

    /**
     * 克隆贵金属综合单据
     * @param {MetalCombineOrder} source
     * @returns {MetalCombineOrder}
     */
    static clone(source) {
        let baseOrder = DocBase.clone(source);

        let metalBalances = [];

        // 拷贝metalBalance
        source._metalBalances.forEach(element => {
            metalBalances.push(CombineMetalBalance.clone(element));
        });

        const order = new MetalCombineOrder({
            targetObject: TargetObject.clone(source.targetObject),
            wareHouse: WareHouse.clone(source.wareHouse),
            salesCommodities: [],
            purchaseCommodities: [],
            receiveableAmount: source._receiveableAmount,
            payableAmount: source._payableAmount,
            receivedAmount: source._receivedAmount,
            paymentAmount: source._paymentAmount,
            fundAccountForReceive: source._fundAccountForReceive,
            fundAccountForPayment: source._fundAccountForPayment,
            quickInventoryMode: source._quickInventoryMode,
            metalBalances: metalBalances,            
            otherFunds: source._otherFunds,
            combineOrderType: source.combineOrderType,
            innerBalance: source._innerBalance,
        });

        Object.assign(order, baseOrder);

        // 拷贝销售商品列表
        source._salesCommodities.forEach(element => {
            order._salesCommodities.push(CommodityBatchWithTax.clone(element));
        });

        // 拷贝回购商品列表
        source._purchaseCommodities.forEach(element => {
            order._purchaseCommodities.push(CommodityBatchWithTax.clone(element));
        });

        

        return order;
    }

    /**
     * 从JSON创建贵金属综合单据
     * @param {Object} json
     * @returns {MetalCombineOrder}
     */
    static fromJson(json) {
        // console.log("MetalCombineOrder.fromJson", json);

        let baseOrder = DocBase.fromJson(json, DocType.MetalCombine);

        // 贵金属收支列表 需要传入构造函数，构造函数中有贵金属补全，不然会重新重复清空 
        let metalBalances = [];

        (json.metalBalanceDetail || []).forEach(item => {
            metalBalances.push(CombineMetalBalance.fromJson(item));
        });

        const order = new MetalCombineOrder({
            targetObject: TargetObject.fromJsonForOrders(json),
            wareHouse: new WareHouse({
                id: Util.jsonToString(json['storageId']),
                name: Util.jsonToString(json['storageName'])
            }),
            salesCommodities: [],
            purchaseCommodities: [],
            receiveableAmount: Util.jsonToCsFundDouble(json['receiveableAmount'], null),
            payableAmount: Util.jsonToCsFundDouble(json['payableAmount'], null),
            receivedAmount: Util.jsonToCsFundDouble(json['receivedAmount'], null),
            paymentAmount: Util.jsonToCsFundDouble(json['paymentAmount'], null),

            fundAccountForReceive: new FundAccount({
                id: Util.jsonToString(json['receiveFundAccountId']),
                name: Util.jsonToString(json['receiveFundAccountName']),
                balance: 0,
                bankName: "",
                income: 0,
                expenses: 0
            }),
            fundAccountForPayment: new FundAccount({
                id: Util.jsonToString(json['paymentFundAccountId']),
                name: Util.jsonToString(json['paymentFundAccountName']),
                balance: 0,
                bankName: "",
                income: 0,
                expenses: 0
            }),
            quickInventoryMode: Util.jsonToBool(json['quickInventoryMode'], true),
            metalBalances: metalBalances,
            innerBalance: Util.jsonToCsFundDouble(json['innerBalance'], null),
            //  otherFunds: OrderOtherFundData.fromJson(json['otherFunds'])

            combineOrderType: CombineOrderType.fromCode(json['combineType']),

            periodId: Util.jsonToString(json['peroidId']),
        });

        Object.assign(order, baseOrder);

        // 销售商品列表
        (json.salesCommodities || []).forEach(item => {
            order._salesCommodities.push(CommodityBatchWithTax.fromJson(item, DocType.MetalCombine));
        });

        // 回购商品列表
        (json.purchaseCommodities || []).forEach(item => {
            order._purchaseCommodities.push(CommodityBatchWithTax.fromJson(item, DocType.MetalCombine));
        });



        // 触发更新balanceAfter
        order.calculatePriceAndQuantity(true);
        order.balanceBefore = CsFundDouble.zero();

        // console.log("MetalCombineOrder.fromJson", json, order);

        return order;
    }

    /**
     * 转换为JSON
     * @returns {Object}
     */
    toJson() {
        const json = super.toJson();
        json.index = this._indexInTransaction;

        // 校验函数过滤了数据不完整情况，只用判断 count 是否为空
        json.salesCommodities = this._salesCommodities
            .filter(element => element.count != null)
            .map(element => element.toJson());

        json.purchaseCommodities = this._purchaseCommodities
            .filter(element => element.count != null)
            .map(element => element.toJson());


        if (this._combineOrderType.code == CombineOrderType.PeriodInitalRnd.code) {
             json.metalBalanceDetail = this._metalBalances.filter(element => element.inCount != null
                || element.outCount != null || element.inExpectCount != null || element.outExpectCount != null || 
                element.innerBalance != null
            ).map(element => element.toJson(this.isPeriodInitial));
        } else {
            json.metalBalanceDetail = this._metalBalances.filter(element => element.inCount != null
                || element.outCount != null || element.inExpectCount != null || element.outExpectCount != null
            ).map(element => element.toJson(this.isPeriodInitial));
        }

        if (this._receivedAmount != null) {
            json.receivedAmount = this._receivedAmount.value;
            json.receiveFundAccountId = this._fundAccountForReceive.id;
        }

        if (this._paymentAmount != null) {
            json.paymentAmount = this._paymentAmount.value;
            json.paymentFundAccountId = this._fundAccountForPayment.id;
        }


        json.objId = this.targetObject.id;
        json.storageId = this.wareHouse.id;


        json.quickInventoryMode = this._quickInventoryMode ? 1 : 0;


        let otherFundStr = this._otherFunds.toJsonStr();

        if (otherFundStr != null) {
            json.otherFunds = otherFundStr;
        }

        if (this.receiveableAmount != null) { json.receiveableAmount = this.receiveableAmount.value; }

        if (this.payableAmount != null) { json.payableAmount = this.payableAmount.value; }

        let payBalance = this.payBalance ?? CsFundDouble.zero();
        let receiveBalance = this.receiveBalance ?? CsFundDouble.zero();
        let swapFee = this.swapFee?.fundDouble ?? CsFundDouble.zero();

        // 期初单据没有 receiveBalance,payBalance,swapFee 只有innerBalance
        if (this.combineOrderType.code === CombineOrderType.PeriodInitalRnd.code) {
            json.innerBalance = this._innerBalance?.value ?? 0;
        }
        else {
            json.innerBalance = receiveBalance.add(payBalance).sub(swapFee).value;
        }

        json.combineType = this._combineOrderType.code; // 1 普通记录 2 期末 3 期初 

        return json;
    }
}